#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"../include/vfs.h"

HEAD add_root(HEAD root,FD* new){

	HEAD temp=malloc(sizeof(struct head));
	
	temp->droot=new;
	temp->left=NULL;
	
	return temp;	 	
}


HEAD add_node(HEAD root,FD* new1,int last){

	Tree new,temp;
	char *cur,*final;
	int flag=1,len;
	
		
	new=malloc(sizeof(Tree));

	new->desc=new1;
	new->left=NULL;
	new->right=NULL;

	if(root->left==NULL){

		root->left=new;
		making=1;
		return root;
	}
	
	temp=root->left;

	while(flag){
	
		if((strstr(new->desc->path,temp->desc->path))!=NULL&&(strcmp(new->desc->path,temp->desc->path)!=0)){
		
			if(temp->left){

				temp=temp->left;
			}
			else{
				temp->left=new;
				flag=0;
				making=1;
			}	
	
		}
		else if(strcmp(new->desc->path,temp->desc->path)==0){

			flag=0;
		}

		else{
			if(temp->right){
				temp=temp->right;
			}
			else
			{
				temp->right=new;
				flag=0;
				making=1;
			}	
			
		}	
	
	}

	return root;	
}


void display(HEAD root){

	if(root){
		Tree temp;
		temp=root->left;
		printf(" %s \t %s ",root->droot->filename,root->droot->path);
		printf("\n(%s)",root->droot->filename);
		display_nodes(temp);
	}
	else 
	{
		//printf("\nEmpty nary tree. ");
	
	}	
}


/*
void display_nodes(Tree node){
	
	if(node){
		if(node->right)
			display_nodes(node->right);
		printf("\n");	.o	
		printf(" %s ",node->desc->filename);
		if(node->left)
			display_nodes(node->left);
		
	}
}
*/

void display_nodes(Tree leaf)
{
    Tree temp;

    temp=leaf;

    if(temp)
    {
	fseek(list_dir,0,SEEK_END);
        fprintf(list_dir,"%s \t %s",temp->desc->filename,temp->desc->path);
        if(temp->right)
        {   fseek(list_dir,0,SEEK_END);
            fprintf(list_dir,"--->\t");
            display_nodes(temp->right);
        }
        if(temp->left)
        {
	   fseek(list_dir,0,SEEK_END);
           fprintf(list_dir,"\n(%s) \t %s \t",temp->desc->filename,temp->desc->path);
            display_nodes(temp->left);
        }

    }

}
HEAD delete_root(HEAD root,FD* new){
	Tree temp;
	if(root->left)
	temp=root->left;
	
	if(!(strcmp(root->droot->path,new->path))){
		root->left=NULL;
		free(root);
	}
	else if(!(strcmp(temp->desc->path,new->path))){
		root->left=temp->right;
		free(temp);
	}
	else
		root=delete_node(root,temp,new);
	
	return root;
}

HEAD delete_node(HEAD root,Tree node,FD* new){
	Tree check,temp,tmp,nod;
	int flag=0;

	temp = root->left;
	tmp=temp;
	nod = node;
	

	while(temp)
	{	
		if(!(strcmp(temp->desc->path,new->path))){
			tmp->left=temp->right;
			free(temp);
			return root;
		}
		flag=0;

		if(nod->right)
		{
			check=nod->right;
		}
		else if(node->left)
		{
			check=nod->left;
		}
		
		while(check&&flag==0){
			
			if(!(strcmp(check->desc->path,new->path))){
				if(check==nod->right){
					nod->right=check->right;
					free(check);
					flag=1;
					
					return root;
					}
				else{
					nod->left=check->right;
					free(check);
					flag=1;
					return root;

				}
			}
			else{
				if(strstr(new->path,check->desc->path)!=NULL){
					nod=check;
					check=check->left;
				}
				else if(check->right){
					nod=check;
					check=check->right;
				}
	
				else{
		
					flag=1;
				}
			}
		}
		tmp=temp;
		temp = temp->left;
		nod = temp;
	}	
return root;	
}	

void list_root(HEAD root,FD* new,int rec,char filepath[]){
	
	Tree tmp;
	
	list_dir = fopen(filepath,"a");

	if(list_dir==NULL){
		list_dir_fail=1;
		return;
	}
	if(root){
		
		tmp=root->left;
		
			if(rec){
		
			display_nodes(tmp);
			}
			else{
		
				while(tmp!=NULL){
					
					fseek(list_dir,0,SEEK_END);
					fprintf(list_dir,"\n %s \t %s\n",tmp->desc->filename,tmp->desc->path);
					tmp=tmp->right;
				}
			}
		}

	else if(!root)
	{
		//printf("\nEmpty nary tree. ");
	}
}

void list_node(HEAD root,FD* new,int rec,char filepath[]){

	int flag;
	Tree temp;

	list_dir = fopen(filepath,"a");

	if(list_dir==NULL){
		list_dir_fail=1;
		return;
	}

	if(root->left){
		
		temp=root->left;
		flag=1;
		while(flag){
			if((strstr(new->path,temp->desc->path))!=NULL&&(strcmp(new->path,temp->desc->path)!=0)){
			if(temp->left){
				temp=temp->left;
			}
			else{
				
				flag=0;
			}	
	
		}
		else if(strcmp(new->path,temp->desc->path)==0){
			if(temp->left){
				//printf("\n The list of files and folders inside current driectory %s are: ",temp->desc->filename);
				if(rec){
					display_nodes(temp->left);
					flag=0;
				}
			
				else{
					temp=temp->left;
					while(temp){
						fseek(list_dir,0,SEEK_END);
						fprintf(list_dir,"\n %s \t \n",temp->desc->filename,temp->desc->path);
						temp=temp->right;
					}
					flag=0;
				}
			}
			else
			{	//printf("\n No contents to list under %s. ",new->filename);
				flag=0;
			}
		}

		else{
			if(temp->right){
				temp=temp->right;
			}
			else
			{
				//printf("\n Folder-File Does not exist.. ");
				flag=0;
			}	
			
		}	
	
	}	
}	

}


HEAD movedirectory(HEAD root, FD *dest, FD *src)
{
	Tree temp1=NULL,temp2=NULL,cur=NULL,check=NULL,catch=NULL,tmp=NULL,dir_check=NULL;
	int flag=1;
	char final_path[100];


	if(strcmp(dest->path,"/")==0)
	{
		root=movedirectory_home(root,dest,src);
		return root;
		
	}

	else
	{
		if(root && root->left)
	{	
			temp1 =root->left;

			while(flag && temp1){

				if((strstr(src->path,temp1->desc->path))!=NULL&&(strcmp(src->path,temp1->desc->path)!=0)){
					if(temp1->left){
						check = temp1;// left or right
						
						temp1=temp1->left;
					}
					else{
						//printf("\n Folder-File Does not exist.. ");
						flag=0;
					}	
		
				}
				else if(strcmp(src->path,temp1->desc->path)==0){
					if(temp1->left){
						
						//printf("\n The list of files and folders inside current driectory %s are: ",new->filename);	
						flag = 0;	
					}
					else{
						//printf("\n No contents to list under %s. ",new->filename);
					flag=0;
					}
				}
	
				else{
					if(temp1->right){
						
						check = temp1;
						temp1=temp1->right;
					}
					else
					{	
						//printf("\n Folder-File Does not exist.. ");
						flag=0;
					}	
				}
			}
	
	}	
		
	
	cur = temp1; //src
	
	if(root && root->left)
	{
		
		temp2 = root->left;
	
		flag = 1;
	
		while(flag && temp2){
			if((strstr(dest->path,temp2->desc->path))!=NULL&&(strcmp(dest->path,temp2->desc->path)!=0)){
				if(temp2->left){
					
					temp2=temp2->left;
				}
				else{
					//printf("\n Folder-File Does not exist.. ");
					flag=0;
				}	
		
			}
			else if(strcmp(dest->path,temp2->desc->path)==0){
				if(temp2->left){
					//printf("\n The list of files and folders inside current driectory %s are: ",new->filename);
					flag = 0;	
				}
				else{
					//printf("\n No contents to list under %s. ",new->filename);
				flag=0;
				}
			}
	
			else{
				if(temp2->right){
					temp2=temp2->right;
				}
				else
				{
					//printf("\n Folder-File Does not exist.. ");
					flag=0;
				}	
				
			}	
		}
	}
	
	catch =temp2; //dest

	if(catch->left!=NULL)
	{
		dir_check = catch->left;

		//printf("\n DIR CHECK: %s",dir_check->desc->path);
		while(dir_check)
		{
			if(strcmp(dir_check->desc->filename,cur->desc->filename)==0)
			{	source_exist=1;
				return root;
			}
			dir_check = dir_check->right;
		}

	}	


	if(cur==root->left)
	{
		root->left=cur->right;
		cur->right = catch->left;
		catch->left = cur;

	}

	else if( cur == check->right)
	{
		check->right = cur->right;
		cur->right = catch->left;
		catch->left = cur;
	}
	else if( cur == check->left)
	{

		check->left = cur->right;
		cur->right = catch->left;
		catch->left = cur;
	}


		// change path of the moved directory contents
	
		strcpy(final_path,catch->desc->path);
		strcat(final_path,"/");


		strcat(final_path,cur->desc->filename);

		strcpy(cur->desc->path,final_path);

		change_path(cur,cur->left);
	}
	return root;
	
}


HEAD move_file(HEAD root, FD *dest, FD *src,int exist,char fname[])
{
	Tree temp1=NULL,temp2=NULL,cur=NULL,check=NULL,catch=NULL,tmp=NULL;
	int flag=1,i=0;
	char final_path[100];

	
	for(i=0;i<80;i++)
	{
		final_path[i]='\0';
	}

	
	if(strcmp(dest->path,"/")==0)
	{
		root=movefile_home(root,dest,src,exist,fname);

		return root;
	}

	else
	{
		if(root && root->left)
	{	
			temp1 =root->left;

			
			while(flag && temp1){
	
				if((strstr(src->path,temp1->desc->path))!=NULL&&(strcmp(src->path,temp1->desc->path)!=0)){
					if(temp1->left){
						check = temp1;// left or right
						
						temp1=temp1->left;
					}
					else{
						//printf("\n Folder-File Does not exist.. ");
						flag=0;
					}	
		
				}
				else if(strcmp(src->path,temp1->desc->path)==0){
					if(temp1->left){
						
						//printf("\n The list of files and folders inside current driectory %s are: ",new->filename);	
						flag = 0;	
					}
					else{
						//printf("\n No contents to list under %s. ",new->filename);
					flag=0;
					}
				}
	
				else{
					if(temp1->right){
						
						check = temp1;
						temp1=temp1->right;
					}
					else
					{	
						//printf("\n Folder-File Does not exist.. ");
						flag=0;
					}	
				}
			}
	
	}	
		
	
	cur = temp1; //src

		

	if(root && root->left)
	{
		
		temp2 = root->left;
	
		flag = 1;
	
		while(flag && temp2){
			if((strstr(dest->path,temp2->desc->path))!=NULL&&(strcmp(dest->path,temp2->desc->path)!=0)){
				if(temp2->left){
					
					temp2=temp2->left;
				}
				else{
					//printf("\n Folder-File Does not exist.. ");
					flag=0;
				}	
		
			}
			else if(strcmp(dest->path,temp2->desc->path)==0){
				if(temp2->left){
					//printf("\n The list of files and folders inside current driectory %s are: ",new->filename);
					flag = 0;	
				}
				else{
					//printf("\n No contents to list under %s. ",new->filename);
				flag=0;
				}
			}
	
			else{
				if(temp2->right){
					temp2=temp2->right;
				}
				else
				{
					//printf("\n Folder-File Does not exist.. ");
					flag=0;
				}	
				
			}	
		}
	}

	catch =temp2; //dest



	if(cur==root->left)
	{
		

		root->left=cur->right;
		cur->right = catch->left;
		catch->left = cur;

	}

	else if( cur == check->right)
	{
		check->right = cur->right;
		cur->right = catch->left;
		catch->left = cur;
	}
	
	else
	{
		check->left = cur->right;
		cur->right = catch->left;
		catch->left = cur;
	}

		//display(root);
		// change path of the moved directory contents

		strcpy(final_path,dest->path);
		strcat(final_path,"/");
		strcat(final_path,fname);

		strcpy(cur->desc->path,final_path);

		

		if(exist==1)
		{
			strcpy(cur->desc->filename,fname);

		}
	
		roots.bstRoot = insert(roots.bstRoot,cur->desc);

	//	printf("\n \n INSERTING %s",cur->desc->filename);
		hashtable_insert(cur->desc);
	
	}
	return root;
	
}

HEAD movefile_home(HEAD root,FD *dest,FD *src,int exist,char fname[])
{
	Tree cur,catch,temp1,check,tmp;
	char final_path[50];
	int flag=1;

		if(root && root->left)
	{	
			temp1 =root->left;

			
			while(flag && temp1){
	
				if((strstr(src->path,temp1->desc->path))!=NULL&&(strcmp(src->path,temp1->desc->path)!=0)){
					if(temp1->left){
						check = temp1;// left or right
						
						temp1=temp1->left;
					}
					else{
						//printf("\n Folder-File Does not exist.. ");
						flag=0;
					}	
		
				}
				else if(strcmp(src->path,temp1->desc->path)==0){
					if(temp1->left){
						
						//printf("\n The list of files and folders inside current driectory %s are: ",new->filename);	
						flag = 0;	
					}
					else{
						//printf("\n No contents to list under %s. ",new->filename);
					flag=0;
					}
				}
	
				else{
					if(temp1->right){
						
						check = temp1;
						temp1=temp1->right;
					}
					else
					{	
						//printf("\n Folder-File Does not exist.. ");
						flag=0;
					}	
				}
			}
	
	}	
		
	
	cur = temp1; //src


		 if(cur==check->right)
		{
			check->right = cur->right;
			cur->right = root->left;
			root->left = cur;
		}

		else
		{
			check->left = cur->right;
			cur->right = root->left;
			root->left = cur;
		}
		

		strcat(final_path,"/");
	
		
		strcat(final_path,fname);

		strcpy(cur->desc->path,final_path);
		
		strcpy(cur->desc->filename,fname);

		roots.bstRoot = insert(roots.bstRoot,cur->desc);

		//printf("\n \n INSERTING %s",cur->desc->filename);
		hashtable_insert(cur->desc);
		
	
	return root;

}

FD* search(HEAD root,FD *fd)
{
	Tree temp;
	int flag=1;

	if(strcmp(fd->path,"/")==0){
		return root->droot;
	}
	if(root && root->left)
	{
		
		temp = root->left;

	
		while(flag){
			if((strstr(fd->path,temp->desc->path))!=NULL&&(strcmp(fd->path,temp->desc->path)!=0)){
				if(temp->left){
					temp=temp->left;
	
				}
				else{
					//printf("\n Folder-File 1 Does not exist.. ");
					flag=0;
				}	
		
			}
			else if(strcmp(fd->path,temp->desc->path)==0){
				if(temp->left)
					dir_empty=1;
		
				return temp->desc;
			}
	
			else{
				if(temp->right){
					temp=temp->right;
				}
				else
				{
					//printf("\n Folder-File Does not exist.. ");
					flag=0;
				}	
				
			}	
		}
	}

	return NULL;
	
}

HEAD movedirectory_home(HEAD root,FD *dest,FD *src)
{
	Tree cur=NULL,catch=NULL,temp1=NULL,check=NULL,tmp=NULL;
	char final_path[50];
	int flag=1;

	//printf("\n root->left:%s",root->left->desc->path);

		if(root && root->left)
	{	
			temp1 =root->left;

			
			while(flag && temp1){
	
				if((strstr(src->path,temp1->desc->path))!=NULL&&(strcmp(src->path,temp1->desc->path)!=0)){
					if(temp1->left){
						check = temp1;// left or right
						
						temp1=temp1->left;
					}
					else{
						//printf("\n Folder-File Does not exist.. ");
						flag=0;
					}	
		
				}
				else if(strcmp(src->path,temp1->desc->path)==0){
					if(temp1->left){
						
						//printf("\n The list of files and folders inside current driectory %s are: ",new->filename);	
						flag = 0;	
					}
					else{
						//printf("\n No contents to list under %s. ",new->filename);
					flag=0;
					}
				}
	
				else{
					if(temp1->right){
						
						check = temp1;
						temp1=temp1->right;
					}
					else
					{	
						//printf("\n Folder-File Does not exist.. ");
						flag=0;
					}	
				}
			}
	
	}	
		
	
	cur = temp1; //src
		

		if(cur==check->right)
		{
			check->right = cur->right;
			cur->right = root->left;
			root->left = cur;
		}

		else
		{
			check->left = cur->right;
			cur->right = root->left;
			root->left = cur;
		}
		
	
		strcat(final_path,"/");		

		strcat(final_path,cur->desc->filename);

		strcpy(cur->desc->path,final_path);

		change_path(cur,cur->left);

	return root;
}

void unmount(Tree leaf, FD *store[],int *fds)
{
	if(leaf!=NULL)
        {	
		store[(*fds)] = malloc(sizeof(FD));
                strcpy(store[(*fds)]->filename,leaf->desc->filename);
		strcpy(store[(*fds)]->path,leaf->desc->path);
		store[(*fds)]->file_type = leaf->desc->file_type;
		store[(*fds)]->file_size = leaf->desc->file_size;
		store[(*fds)]->block_no = leaf->desc->block_no;
		(*fds)++;
                unmount(leaf->right,store,fds);
                unmount(leaf->left,store,fds);
        }  
  
}

void change_path(Tree current,Tree start)
{

	//printf("\n\n\n CHANGE PATH");
	if(start)
	{
		strcpy(start->desc->path,current->desc->path);
		strcat(start->desc->path,"/");
		strcat(start->desc->path,start->desc->filename);

		roots.bstRoot = insert(roots.bstRoot,start->desc);
				
			if(start->desc->file_type>0){
				//printf("\n \n INSERTING %s",current->desc->filename);
				hashtable_insert(start->desc);
			}
		change_path(current,start->right);
		
		change_path(start,start->left);
	}

}








